package com.funcpro.common.utils;


import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.StatusLine;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.util.EntityUtils;

import javax.net.ssl.SSLContext;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;


/*
 * @author ZYT
 * @desc httpclient连接池版本
 * @time 2023-04-14 17:22
 */

@Slf4j
public class HttpClientUtils {
    private HttpClientUtils(){}

    //多线程共享实例
    private static CloseableHttpClient httpClient;
    static{
        SSLContext sslContext=createSSLContext();
        SSLConnectionSocketFactory sslsy = new SSLConnectionSocketFactory(sslContext, NoopHostnameVerifier.INSTANCE);
        // 注册http套接字工厂和https套接字工厂
        Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory> create()
        .register( "http", PlainConnectionSocketFactory.INSTANCE)
        .register("https",sslsy)
                .build();
        // 连接池管理器
        PoolingHttpClientConnectionManager connMgr=new PoolingHttpClientConnectionManager(socketFactoryRegistry);
        connMgr.setMaxTotal(100);//最大连接数
        connMgr.setDefaultMaxPerRoute(50);
        connMgr.setValidateAfterInactivity(5 * 1000);
        RequestConfig requestConfig=RequestConfig.custom()
                .setConnectTimeout(3000)
                .setSocketTimeout(3000)
                .setConnectionRequestTimeout(3000)
                .build();
        httpClient= HttpClients.custom()
                .setConnectionManager(connMgr)
                .setDefaultRequestConfig(requestConfig)
                .build();
    }

    public static String postJsonObject(String url,String jsonObject) throws IOException{
        HttpPost httpPost = new HttpPost(url);
        StringEntity entity = new StringEntity(jsonObject, Charset.forName("UTF-8"));
        httpPost.setHeader("Content-Type", "application/json;charset=UTF-8");
        httpPost.setHeader("Accept", "application/json");
        httpPost.setEntity(entity);
        HttpResponse response = httpClient.execute(httpPost); // 发送请求并保存返回值到HttpResponse对象中
        HttpEntity responseEntity = response.getEntity(); // 从HttpResponse对象中获取返回的实体
        String responseBody = EntityUtils.toString(responseEntity, StandardCharsets.UTF_8);
        StatusLine statusLine = response.getStatusLine(); // 从HttpResponse对象中获取状态行信息
        if (statusLine.getStatusCode() == 200) {
            log.info("华夏文章推送到一财成功：" + jsonObject);
            return responseBody;
        } else if (statusLine.getStatusCode() == 401) {
            log.error("定时请求一财报错信息为：应用验证失败返回" + jsonObject);
            throw new IOException("应用验证失败返回" + statusLine.getStatusCode());
        } else if (statusLine.getStatusCode() == 422) {
            log.error("定时请求一财报错信息为：缺必须字段或者件重复返回" + jsonObject);
            throw new IOException("缺必须字段或者件重复返回" + statusLine.getStatusCode());
        } else {
            log.error("请求异常" + jsonObject);
            throw new IOException("请求异常" + statusLine.getStatusCode());
        }

    }

    public static String postImage(String url,byte[] imgData) throws IOException{

        HttpPost httpPost = new HttpPost(url);
        httpPost.setHeader("connection", "Keep-Alive");
        httpPost.setHeader("Content-Type", "application/octet-stream");
        httpPost.setHeader("x-ti-app-id", "8a2224a93c5ff440353f0cfd470f0526");
        httpPost.setHeader("x-ti-secret-code", "99b9a5eeae49ae98408f33510a46d445");
        ByteArrayEntity entity = new ByteArrayEntity(imgData);
        httpPost.setEntity(entity);
        HttpResponse response = httpClient.execute(httpPost); // 发送请求并保存返回值到HttpResponse对象中
        HttpEntity responseEntity = response.getEntity(); // 从HttpResponse对象中获取返回的实体
        String responseBody = EntityUtils.toString(responseEntity, StandardCharsets.UTF_8);
        StatusLine statusLine = response.getStatusLine(); // 从HttpResponse对象中获取状态行信息
        if (statusLine.getStatusCode() == 200) {
            return responseBody;
        } else if (statusLine.getStatusCode() == 40301) {

            throw new IOException("没有http body" + statusLine.getStatusCode());
        } else if (statusLine.getStatusCode() == 40600) {
            throw new IOException("图片解码失败" + statusLine.getStatusCode());
        } else {
            throw new IOException("请求异常" + statusLine.getStatusCode());
        }

    }











    private static SSLContext createSSLContext() {
        try {
            TrustStrategy acceptingTrustStrategy=(cert, authType) ->true;
            return SSLContexts.custom().loadTrustMaterial(null,acceptingTrustStrategy).build();
        } catch (Exception e) {
            log.error("初始化ssl配置失败",e);
            throw new RuntimeException("初始化ssl配置失败");
        }
    }


}
